TCP DUP ACK抓包分析

您所在的位置:网站首页 tcp 重传 TCP DUP ACK抓包分析

TCP DUP ACK抓包分析

2023-11-27 23:36| 来源: 网络整理| 查看: 265

推荐先学习一下: https://baijiahao.baidu.com/s?id=1724881650117896078&wfr=spider&for=pc https://baijiahao.baidu.com/s?id=1722020000117796049&wfr=spider&for=pc

WireShark出现的常见提示:

Packet size limited during capture:标记了的包没抓全TCP Previous segment not captured:Wireshark 发现后一个包的 Seq 大于 Seq+Len,就知道中间缺失了一段。TCP ACKed unseen segment:发现被 Ack 的那个包没被抓到,就会提示。TCP Out-of-Order:后一个包的 Seq 号小于前一个包的 Seq+Len 时。TCP Dup ACK:当乱序或丢包发生时,接收方会收到一些 Seq 号比期望值大的包。没收到一个这种包就会 Ack 一次期望的 Seq 值,提现发送方。TCP Fast Retransmission:三次DUP ACK之后出发快速重传。(发送端后端观测,前端抓包看一个Dup ACK就发出了,应该是有缓存,3个DUP ACK之后才真正发出)TCP Retransmission:发送方只好等到超时了再重传。TCP zerowindow:0窗口,没法再收。TCP window Full:窗口耗尽。没法再发!Time-to-live exceeded:分片无法正常组装 案例一

vm client:172.18.21.57 vm server:172.18.42.13

在 vm client 执行 wget 从 server 下载大文件速度逐渐变为0 ,进行抓包分析: 在这里插入图片描述 1, No.50 为client收到的 server发送数据,Seq=113587,Ack=660, Len=2576。 那么No.51 client回复的Ack=113587+2576=116163. 即 Seq=660,Ack=116163, Len=0

2, 同时116163也是期望收到的下一个数据的Seq. 即收到了No.52, Seq=116163,Ack=660, Len=2576; 再下一个收到了数据的Seq=116163+2576=118739. 即No.53,Seq=118739,Ack=660, Len=1288;

3, 再下一个期望收到数据的Seq=118739+1288=120027。在 No.55 client回复Ack=120027, Len=0 但No.54,提前收到了Seq=121315,Ack=660, Len=1288;报文被标识为TCP Previous segment not captured,表示此报文之前的一个或多个报文没有被捕获到(即Seq=120027的包没收到)。

4,No.56,基于No.54收到了的Seq=121315+1288=122603, Ack=660,Len=2576

5,No.57, Dup Ack=120027, Len=0 client发现预期的报文(即Seq=120027)迟迟没收到,便会发送重复的ack报文请求丢失的第一个报文,从而出现被标识为TCP dup ack的报文(重复应答),#前的表示报文到哪个序号丢失,#后面的是表示第几次丢失(可能由于乱序还没收到,也可能真的丢了)

6, No.58 终于收到了期望的Seq=120027的报文,但是OutOf-Order

在server端确认这一次收到的Seq=120027只是由于乱序到达慢了,并不是由于前一个丢包后DUP ACK之后的重新换包,而且server端抓包发现收到DUP ACK之后并没有回重传包!: 在这里插入图片描述 发送Seq=113587的数据在No.37. 连续发送了两个数据: No.37,Seq=113587,Ack=660, Len=21896; No.38,Seq=135483,Ack=660, Len=30912; No.39,收到了client回的Ack=116163 No.40和No.41收到了client要求重传的Ack,但是并没有重传!再往后看: 在这里插入图片描述 TCP Dup ACK 发送了多达47次都没有回, 而TCP Retransmission原因很明显是上面的超时引发的数据重传,并没有快速重传

虚拟机里sysctl有个配置项 net.ipv4.tcp_sack = 1, 经确认已经启用 #启用有选择的应答(Selective Acknowledgment), #这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段); #(对于广域网通信来说)这个选项应该启用,但是这会增加对 CPU 的占用。

最终确认问题导致原因如下:

问题现象 当出现以下条件共存的情况下会出现scp速度变为0问题。 1,设置防火墙规则过滤掉sack-permitted、sack 报文头信息: [root@EulerOS-BaseTemplate ~]# iptables -L -t mangle … Chain INPUT (policy ACCEPT) target prot opt source destination TCPOPTSTRIP tcp – anywhere anywhere TCPOPTSTRIP options mss,sack-permitted,sack,timestamp,md5 … 2,设置 tcp_sack = 1 [root@EulerOS-BaseTemplate ~]# sysctl -a | grep tcp_sack net.ipv4.tcp_sack = 1

3,在链路上发生丢包。

原因分析 net.ipv4.tcp_sack与防火墙规则冲突导致。 tcp_sack 设置快速重传,但是防火墙规则把sack需要的信息给strip掉了,导致重传的数据失效,只能慢速传输,速度到最低。 在不发生丢包的情况下,没有触发重传场景,则不复现该问题。

解决方法 有两种修改方法,解决冲突问题: 打开sack功能,把防火墙过滤sack-permitted,sack规则去掉,在丢包场景下tcp性能较好。 关闭sack功能,设置net.ipv4.tcp_sack = 0,在丢包乱序场景下tcp性能较差。

案例二

iperf3打ipv6测试,接收端虚拟机抓包,发现每次都是最后的[PSH,ACK]报文乱序导致重传:

在这里插入图片描述

刚开始怀疑镜像gro有问题,于是关闭gro后测试,依然会重传:

在这里插入图片描述 而且可以注意到: seq=972202的包已经收到了, 那么回包的ACK应该是972202+1124=973326. 但是回的ACK(包括Dup ACK)却是972202,应该是上一个包的ACK!

用wirshark打开分析,发现这个[PSH,ACK]报文的checksum计算正确,但ip头里的length填写错误,导致虚拟机把它作为了错包!

在这里插入图片描述

虚拟机内可以用 nstat -z -as 看到统计。统计说明见wiki: https://www.kernel.org/doc/html/latest/networking/snmp_counter.html

这里正好回顾下gsogro的知识:

对于上面出问题的seq=972202数据包,在发送端抓包,属于如下tso大包:

在这里插入图片描述

包长15404, 对应tcp头里的 [TCP Segment Len: 15404] 字段;ipv6头 [Payload length: 15436]

接受端已被网卡切成小包, 每个ip长度为1460(ipv4为1500,跟mtu有关),每个tcp长度为1428,则15404被网卡切成:1428 x 10 + 1124, 即最后一片[PSH,ACK]的报文tcp头部长度应为1124, ipv6头部长度应为1156.

除此之外, checksum也是比较容易出现校验错误的地方。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3